/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import diagram.Graphical;
import diagram.Node;
import diagram.handles.ConnectHandle;
import diagram.handles.TriggerHandle;
import diagram.handles.Handle;
import diagram.handles.InputHandle;
import diagram.handles.OutputHandle;
import diagram.handles.ResizeHandle;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Observable;
import java.util.Set;

/**
 *
 * @author Jelle
 */
public class DiagramModel extends Observable implements Serializable {

    private ArrayList<Graphical> objects = new ArrayList<Graphical>();
    private ArrayList<Graphical> selection = new ArrayList<Graphical>();
    private boolean attachable = false;

    public DiagramModel() {
    }

    public ArrayList<Graphical> getObjects(String type) {
        ArrayList<Graphical> set = new ArrayList<Graphical>();
        if (type.equals("all")) {
            for (Graphical g : objects) {
                set.add(g);
            }
        } else if (type.equals("node")) {
            for (Graphical g : objects) {
                if (g.getClass().getName().equals("diagram.Node")) {
                    set.add(g);
                }
            }
        } else if (type.equals("handle")) {
            for (Graphical g : objects) {
                if (g.getClass().getName().startsWith("diagram.handles.")) {
                    set.add(g);
                }
            }
        } else if (type.equals("connection")) {
            for (Graphical g : objects) {
                if (g.getClass().getName().startsWith("diagram.connections.")) {
                    set.add(g);
                }
            }
        } else if (type.equals("triggerhandle")) {
            for (Graphical g : objects) {
                if (g.getClass().getName().equals("diagram.handles.TriggerHandle")) {
                    set.add(g);
                }
            }
        } else if (type.equals("inputhandle")) {
            for (Graphical g : objects) {
                if (g.getClass().getName().equals("diagram.handles.InputHandle")) {
                    set.add(g);
                }
            }
        } else if (type.equals("outputhandle")) {
            for (Graphical g : objects) {
                if (g.getClass().getName().equals("diagram.handles.OutputHandle")) {
                    set.add(g);
                }
            }
        } else if (type.equals("connecthandle")) {
            for (Graphical g : objects) {
                if (g.getClass().getName().equals("diagram.handles.ConnectHandle")) {
                    set.add(g);
                }
            }
        } else if (type.equals("trianglehandle")) {
            for (Graphical g : objects) {
                if (g.getClass().getName().equals("diagram.handles.TriangleHandle")) {
                    set.add(g);
                }
            }
        } else if (type.equals("triggerconnection")) {
            for (Graphical g : objects) {
                if (g.getClass().getName().equals("diagram.connections.TriggerConnection")) {
                    set.add(g);
                }
            }
        } else if (type.equals("handleconnection")) {
            for (Graphical g : objects) {
                if (g.getClass().getName().equals("diagram.handles.HandleConnection")) {
                    set.add(g);
                }
            }
        }
        return set;
    }

    public void removeObject(Graphical g) {
        objects.remove(g);
        selection.remove(g);
        sortGraphSet();
        adjustView();
    }

    public void addObject(Graphical g) {
        objects.add(g);
        sortGraphSet();
        adjustView();
    }

    public void editNode(Node node, String value, String w) {
        for (Graphical ni : getObjects("node")) {
            Node n = (Node) ni;
            if (n.equals(node)) {
                if (w.equals("name")) {
                    n.setName(value);
                } else if (w.equals("type")) {
                    n.setType(value);
                }
            }
        }
        adjustView();
    }

    public void removeAll() {
        objects.clear();
    }

    public Set<Graphical> getAttachedObjects(Graphical base, String type) {
        Set<Graphical> setb = new HashSet<Graphical>();
        Iterator<Graphical> it;
        if (base.getClass().getName().equals("diagram.Node")) {
            if (type.equals("all")) {
                it = getObjects("all").iterator();
                while (it.hasNext()) {
                    Graphical g = it.next();
                    if(g.getClass().getName().startsWith("diagram.handles.")){
                        Handle h = (Handle)g;
                        if(h.getBase().equals(base)){
                            setb.add(g);
                        }
                    }
                    
                }
            } else if (type.equals("resizehandle")) {
                it = getObjects("resizehandle").iterator();
                while (it.hasNext()) {
                    Graphical g = it.next();
                    if (base.equals(((ResizeHandle) g).getBase())) {
                        setb.add(g);
                    }
                }
            } else if (type.equals("triggerhandles")) {
                it = getObjects("triggerhandle").iterator();
                while (it.hasNext()) {
                    Graphical g = it.next();
                    if (base.equals(((TriggerHandle) g).getBase())) {
                        setb.add(g);
                    }
                }
            } else if (type.equals("inputhandles")) {
                it = getObjects("inputhandle").iterator();
                while (it.hasNext()) {
                    Graphical g = it.next();
                    if (base.equals(((InputHandle) g).getBase())) {
                        setb.add(g);
                    }
                }
            } else if (type.equals("outputhandles")) {
                it = getObjects("outputhandle").iterator();
                while (it.hasNext()) {
                    Graphical g = it.next();
                    if (base.equals(((OutputHandle) g).getBase())) {
                        setb.add(g);
                    }
                }
            } else if (type.equals("connecthandles")) {
                it = getObjects("connecthandle").iterator();
                while (it.hasNext()) {
                    Graphical g = it.next();
                    if (base.equals(((ConnectHandle) g).getBase())) {
                        setb.add(g);
                    }
                }
            }

        } else if (base.getClass().getName().equals("diagram.handles.InputHandle")) {
            it = getObjects("triggerhandle").iterator();
            while (it.hasNext()) {
                Graphical g = it.next();
                if (base.equals(((ConnectHandle) g).getBase())) {
                    setb.add(g);
                }
            }
        }
        return setb;
    }

    public Graphical getAttachedObject(Graphical base, String type) {
        Graphical setb = null;
        Iterator<Graphical> it;
        if (base.getClass().getName().equals("diagram.Node")) {
            if (type.equals("resizehandle")) {
                it = getObjects("resizehandle").iterator();
                while (it.hasNext()) {
                    Graphical g = it.next();
                    if (base.equals(((ResizeHandle) g).getBase())) {
                        setb = g;
                    }
                }
            }
        }
        return setb;
    }

    /**
     * @return the handles
     */
    void printHandles() {
        Iterator itt = getObjects("handle").iterator();
        while (itt.hasNext()) {
            Handle h = (Handle) itt.next();
            System.out.println("h:" + h.toString());
        }
    }

    public void setGraphicalSelected(Graphical g, boolean value) {
        Iterator<Graphical> it = getObjects("all").iterator();
        while (it.hasNext()) {
            Graphical gr = it.next();
            if (g.equals(gr)) {
                gr.setSelected(value);
                if (value) {
                    addToSelection(gr);
                } else {
                    removeFromSelection(gr);
                }
            }
        }
        adjustView();
    }

    /**
     * @return the handles
     */
    public void setHandleHighLighted(Handle h, boolean value) {
        Iterator it = getObjects("handle").iterator();
        while (it.hasNext()) {
            Handle ha = (Handle) it.next();
            if (ha.equals(h)) {
                ha.setHighlighted(value);
            }
        }
        adjustView();
    }

    /**
     * @param handlesSelection the handlesSelection to set
     */
    public void addToSelection(Graphical s) {
        if (!selection.contains(s)) {
            selection.add(s);
        }
        adjustView();
    }

    public void removeFromSelection(Graphical s) {
        selection.remove(s);
        adjustView();
    }

    /**
     * @return the handlesSelection
     */
    public ArrayList<Graphical> getSelection(String s) {
        ArrayList<Graphical> setb = new ArrayList<Graphical>();
        if (s.equals("all")) {
            System.out.println("all selection");
            for (Graphical g : selection) {
                setb.add(g);
            }
        } else if (s.equals("handle")) {
            System.out.println("handle selection");
            for (Graphical g : selection) {
                if (g.getClass().getName().toString().equals("diagram.handles.TriggerHandle") || g.getClass().getName().toString().equals("diagram.handles.InputHandle")) {
                    setb.add(g);
                }
            }
        } else if (s.equals("node")) {
            System.out.println("node selection");
            for (Graphical g : selection) {
                if (g.getClass().getName().toString().equals("diagram.Node")) {
                    setb.add(g);
                }
            }
        }

        System.out.println("size selection" + setb.size());
        return setb;
    }

    public Graphical getSelected() {
        return selection.get(selection.size() - 1);
    }

    /**
     * @param handlesSelection the handlesSelection to set
     */
    public void clearSelection() {
        selection.clear();
        adjustView();
    }

    public void printSelection() {
        System.out.print("De selectie bevat: ");
        for (int i = 0; i < selection.size(); i++) {
            System.out.print(selection.get(i).getClass().getName() + " ");
        }
        System.out.println("");

    }

    /**
     * @param selection the selection to set
     */
    public void setSelection(ArrayList<Graphical> selection) {
        this.selection = selection;
        adjustView();
    }

    protected void adjustView() {
        
        setChanged();
        notifyObservers();
    }

    /**
     * @return the isAttachable
     */
    public boolean isAttachable() {
        return attachable;
    }

    /**
     * @param isAttachable the isAttachable to set
     */
    public void setAttachable(boolean attachable) {
        this.attachable = attachable;
    }

    /**
     * @param objects the objects to set
     */
    public void setObjects(ArrayList<Graphical> objects) {
        this.objects = objects;
    }

    public void sortGraphSet(){
        Collections.sort(objects, new Comparator<Graphical>(){
            public int compare(Graphical o1, Graphical o2) {
                if(o1.getLevel()<o2.getLevel()){
                return -1;
                }
                else if(o1.getLevel()==o2.getLevel()){
                    return 0;
                }
                else{
                    return 1;
                }
            }


        });
        for( Graphical g : objects){
            System.out.println(g.getClass().getName()+"-"+g.getLevel());
        }
    }
}
